package org.jsola.hr.common.oneKeyPay;

import lombok.extern.slf4j.Slf4j;
import org.jsola.exception.ParamException;
import org.jsola.hr.vo.payPingAn.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * 平安银行代发代扣
 *
 * @author lyh
 */
@Slf4j
public class PingAnBankPay {

    public static void main(String[] args) throws UnsupportedEncodingException {
        /**
         * 填A001
         */
        String 报文类别 = "A001";
        /**
         *  配置项
         * 银企直联目标系统编码为01
         */
        String 目标系统编号 = "01";
        /**
         * 01：GBK
         * 02：UTF-8
         * 建议使用GBK编码
         */
        String 报文编码 = "01";
        /**
         * 01：TCP
         * 02：http
         */
        String 通讯协议 = "01";
        /**
         * 配置项
         * 签约银企直联银行提供给企业的20位唯一的标识代码（银企代码/企业代码）
         */
        String 企业银企直连标准代码 = "0090108040000df22000";
        // 10位  不足左补0
//        String 接收报文长度 = "0000000681";
        String 接收报文长度 = "0000000721";
        // 6位  不足右补空格
        String 交易码 = "4047  ";
        String 操做员代码 = "00000";
        // 01-请求  02-应答
        String 服务类型 = "01";
        String 交易日期 = "20211113";
        String 交易时间 = "141001";
        String 请求方系统流水号 = "whahywhshr2022010503";
        // 请求时必须填写000000  非“000000”代表交易受理异常或失败
        String 返回码 = "000000";
        String msg = 报文类别 + 目标系统编号 + 报文编码 + 通讯协议 + 企业银企直连标准代码 + 接收报文长度 + 交易码 +
                操做员代码 + 服务类型 + 交易日期 + 交易时间 + 请求方系统流水号 +
                "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
                "<?xml version=\"1.0\" encoding=\"GBK\"?>" +
                "<Result>" +
                "<AGREE_NO>E000102307</AGREE_NO>" +
                "<BusiType>04900</BusiType>" +
                "<PayType>1</PayType>" +
                "<Currency>RMB</Currency>" +
                "<SrcAccNo>15000100973868</SrcAccNo>" +
                "<TotalNum>2</TotalNum>" +
                "<TotalAmount>50</TotalAmount>" +
                "<SettleType>1</SettleType>" +
                "<HOResultSet4047R>" +
                "<SThirdVoucher>whahy11230001</SThirdVoucher>" +
                "<OppAccNo>6230580000054008325</OppAccNo>" +
                "<OppAccName>祖起</OppAccName>" +
                "<Amount>20</Amount>" +
                "</HOResultSet4047R>" +
                "<HOResultSet4047R>" +
                "<SThirdVoucher>whahy11230002</SThirdVoucher>" +
                "<OppAccNo>62284808902677</OppAccNo>" +
                "<OppAccName>杨枫</OppAccName>" +
                "<OthBankFlag>Y</OthBankFlag>" +
                "<Amount>30</Amount>" +
                "</HOResultSet4047R>" +
                "<ThirdVoucher>whahywhshr2022010503</ThirdVoucher>" +
                "<BatchOrdRemark>20220104备注</BatchOrdRemark>" +
                "</Result>";

//        System.out.println(msg);
//        String returnStr = tcpPost("127.0.0.1", 7073, msg);
//        System.out.println("returnStr:" + returnStr);
//        returnStr = returnStr.substring(returnStr.indexOf("<"));
//        ReturnHOResultSet4047RVO returnHOResultSet4047RVO = converyToReturnHOResultSet4047RVO(returnStr, ReturnHOResultSet4047RVO.class);
//        System.out.println(returnHOResultSet4047RVO.toString());
//        System.out.println(returnStr);
//        ss();


        // 查询平安银行批次结果
        /**
         * 填A001
         */
        String 报文类别2 = "A001";
        /**
         *  配置项
         * 银企直联目标系统编码为01
         */
        String 目标系统编号2 = "01";
        /**
         * 01：GBK
         * 02：UTF-8
         * 建议使用GBK编码
         */
        String 报文编码2 = "01";
        /**
         * 01：TCP
         * 02：http
         */
        String 通讯协议2 = "01";
        /**
         * 配置项
         * 签约银企直联银行提供给企业的20位唯一的标识代码（银企代码/企业代码）
         */
        String 企业银企直连标准代码2 = "0090108040000df22000";
        // 10位  不足左补0
        String 接收报文长度2 = "0000000102";
        // 6位  不足右补空格 // 配置项
        String 交易码2 = "4048  ";
        String 操做员代码2 = "00000";
        // 01-请求  02-应答
        String 服务类型2 = "01";
        String 交易日期2 = "20211231";
        String 交易时间2 = "104300";
        String 请求方系统流水号2 = "whahywhshr2022010501";
        // 请求时必须填写000000  非“000000”代表交易受理异常或失败
        String 返回码2 = "000000";
        String msg2 = 报文类别2 + 目标系统编号2 + 报文编码2 + 通讯协议2 + 企业银企直连标准代码2 + 接收报文长度2 + 交易码2 +
                操做员代码2 + 服务类型2 + 交易日期2 + 交易时间2 + 请求方系统流水号2 + 返回码2 +
                "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
//                "000000000000000" +
                "<?xml version=\"1.0\" encoding=\"GBK\"?>" +
                "<Result>" +
                "<ThirdVoucher>whahywhshr2022010503</ThirdVoucher>" +
                "</Result>";
//        String returnStr2 = tcpPost("127.0.0.1", 7073, msg2);
//        System.out.println(returnStr2);
//        returnStr2 = returnStr2.substring(returnStr2.indexOf("<?xml"));
//        PingAnBankSelectBatchVO pingAnBankSelectBatchVO = converyToPingAnBankSelectBatchVO(returnStr2, PingAnBankSelectBatchVO.class);
//        System.out.println(pingAnBankSelectBatchVO.toString());


        // 查询账户余额
        /**
         * 填A001
         */
        String 报文类别3 = "A001";
        /**
         *  配置项
         * 银企直联目标系统编码为01
         */
        String 目标系统编号3 = "01";
        /**
         * 01：GBK
         * 02：UTF-8
         * 建议使用GBK编码
         */
        String 报文编码3 = "01";
        /**
         * 01：TCP
         * 02：http
         */
        String 通讯协议3 = "01";
        /**
         * 配置项
         * 签约银企直联银行提供给企业的20位唯一的标识代码（银企代码/企业代码）
         */
        String 企业银企直连标准代码3 = "0090108040000df22000";
        // 10位  不足左补0
        String 接收报文长度3 = "0000000086";
        // 6位  不足右补空格 // 配置项
        String 交易码3 = "4001  ";
        String 操做员代码3 = "00000";
        // 01-请求  02-应答
        String 服务类型3 = "01";
        String 交易日期3 = "20211231";
        String 交易时间3 = "104300";
        String 请求方系统流水号3 = "whahywhshr2022010501";
        // 请求时必须填写000000  非“000000”代表交易受理异常或失败
        String 返回码3 = "000000";
        String msg3 = 报文类别3 + 目标系统编号3 + 报文编码3 + 通讯协议3 + 企业银企直连标准代码3 + 接收报文长度3 + 交易码3 +
                操做员代码3 + 服务类型3 + 交易日期3 + 交易时间3 + 请求方系统流水号3 + 返回码3 +
                "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
                "<?xml version=\"1.0\" encoding=\"GBK\"?>" +
                "<Result>" +
                "<Account>15000100973868</Account>" +
                "</Result>";
//        String returnStr3 = tcpPost("127.0.0.1", 7073, msg3);
//        System.out.println(returnStr3);
//        returnStr3 = returnStr3.substring(returnStr3.indexOf("<?xml"));
//        PingAnBankSelectAccountInfoVO pingAnBankSelectBatchVO = PingAnBankPay.converyToPingAnBankSelectAccountInfoVO(returnStr3,
//                PingAnBankSelectAccountInfoVO.class);
//        System.out.println(pingAnBankSelectBatchVO);


        // 查询账户历史明细
        /**
         * 填A001
         */
        String 报文类别4 = "A001";
        /**
         *  配置项
         * 银企直联目标系统编码为01
         */
        String 目标系统编号4 = "01";
        /**
         * 01：GBK
         * 02：UTF-8
         * 建议使用GBK编码
         */
        String 报文编码4 = "01";
        /**
         * 01：TCP
         * 02：http
         */
        String 通讯协议4 = "01";
        /**
         * 配置项
         * 签约银企直联银行提供给企业的20位唯一的标识代码（银企代码/企业代码）
         */
        String 企业银企直连标准代码4 = "0090108040000df22000";
        // 10位  不足左补0
        String 接收报文长度4 = "0000000232";
        // 6位  不足右补空格 // 配置项
        String 交易码4 = "4013  ";
        String 操做员代码4 = "00000";
        // 01-请求  02-应答
        String 服务类型4 = "01";
        String 交易日期4 = "20211231";
        String 交易时间4 = "104300";
        String 请求方系统流水号4 = "whahywhshr2022010501";
        // 请求时必须填写000000  非“000000”代表交易受理异常或失败
        String 返回码4 = "000000";
        String msg4 = 报文类别4 + 目标系统编号4 + 报文编码4 + 通讯协议4 + 企业银企直连标准代码4 + 接收报文长度4 + 交易码4 +
                操做员代码4 + 服务类型4 + 交易日期4 + 交易时间4 + 请求方系统流水号4 + 返回码4 +
                "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" +
                "<?xml version=\"1.0\" encoding=\"GBK\"?>" +
                "<Result>" +
                "<AcctNo>15000100973868</AcctNo>" +
                "<CcyCode>RMB</CcyCode>" +
                "<BeginDate>20220118</BeginDate>" +
                "<EndDate>20220118</EndDate>" +
                "<PageNo>1</PageNo>" +
                "<PageSize>100</PageSize>" +
                "<OrderMode>001</OrderMode>" +
                "</Result>";

        String ssss =  "<?xml version=\"1.0\" encoding=\"GBK\"?>" +
                "<Result>" +
                "<AcctNo>15000100973868</AcctNo>" +
                "<CcyCode>RMB</CcyCode>" +
                "<BeginDate>20220118</BeginDate>" +
                "<EndDate>20220118</EndDate>" +
                "<PageNo>1</PageNo>" +
                "<PageSize>100</PageSize>" +
                "<OrderMode>001</OrderMode>" +
                "</Result>";
        System.out.println(ssss.getBytes("GBK").length);
        String returnStr4 = tcpPost("127.0.0.1", 7073, msg4);
        System.out.println(returnStr4);
//        returnStr3 = returnStr3.substring(returnStr3.indexOf("<?xml"));
//        PingAnBankSelectAccountInfoVO pingAnBankSelectBatchVO = PingAnBankPay.converyToPingAnBankSelectAccountInfoVO(returnStr3,
//                PingAnBankSelectAccountInfoVO.class);
//        System.out.println(pingAnBankSelectBatchVO);



    }


    public static String tcpPost(String clientIp, int clientPort, String msg) {
        String respData;
        try {
            Socket socket = new Socket(clientIp, clientPort);
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write(msg.getBytes("GBK"));
            outputStream.flush();
            socket.shutdownOutput();

            InputStream inputStream = socket.getInputStream();
            ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
            //这里最好是1024~8192之间
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                bytesOut.write(buffer, 0, len);
            }
            respData = bytesOut.toString("GBK");
            bytesOut.close();
            inputStream.close();
            outputStream.close();
            socket.close();
            return respData;
        } catch (IOException e) {
            e.printStackTrace();
            throw new ParamException("请求银行前置机出错，请联系管理员!");
        }
    }

    public static void ss() {
        PingAnBankTransferVO pingAnBankTransferVO = new PingAnBankTransferVO();
        pingAnBankTransferVO.setThirdVoucher("whahywhshr");
        pingAnBankTransferVO.setAGREE_NO("E000102307");
        pingAnBankTransferVO.setBusiType("04900");
        pingAnBankTransferVO.setPayType("payType");
        List<HOResultSet4047RVO> hoResultSet4047RVOList = new ArrayList<>();
        HOResultSet4047RVO hoResultSet4047RVO = new HOResultSet4047RVO();
        hoResultSet4047RVO.setOppAccName("杨枫");
        hoResultSet4047RVO.setAmount("123");
        hoResultSet4047RVO.setOppAccNo("5215");
        hoResultSet4047RVO.setSThirdVoucher("asdasd");
        hoResultSet4047RVOList.add(hoResultSet4047RVO);
        HOResultSet4047RVO hoResultSet4047RVO1 = new HOResultSet4047RVO();
        hoResultSet4047RVO1.setOppAccName("000");
        hoResultSet4047RVO1.setOppAccNo("00");
        hoResultSet4047RVO1.setSThirdVoucher("00");
        hoResultSet4047RVOList.add(hoResultSet4047RVO1);
        pingAnBankTransferVO.setHOResultSet4047R(hoResultSet4047RVOList);
        System.out.println(convertToXml(pingAnBankTransferVO, "GBK"));

        ReturnHOResultSet4047RVO returnHOResultSet4047RVO = new ReturnHOResultSet4047RVO();
        returnHOResultSet4047RVO = converyToReturnHOResultSet4047RVO("A0010101010090108040000df2200000000002464047  000000220211113141001whahywhshr2021122704000000:交易受理成功                                                                                       00000000000000000000000000000<?xml version=\"1.0\" encoding=\"GBK\" ?><Result><ThirdVoucher>whahy00004</ThirdVoucher><PayType>1</PayType><SrcAccNo>15000100973868</SrcAccNo><TotalNum>2</TotalNum><TotalAmount>50</TotalAmount><BussFlowNo>8043432112272454069543</BussFlowNo></Result>", ReturnHOResultSet4047RVO.class);
    }

    /**
     * 对象转XML
     *
     * @param obj      需要转换的object
     * @param encoding 编码
     * @return XML字符串
     */
    public static String convertToXml(Object obj, String encoding) {
        String result = "";
        try {
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
            StringWriter writer = new StringWriter();
            marshaller.marshal(obj, writer);
            result = writer.toString();
        } catch (Exception e) {
            e.getMessage();
            System.out.println(e.getMessage());
        }
        return result;
    }


    /**
     * xml转换成ReturnHOResultSet4047RVO
     *
     * @param xml
     * @param c
     * @return
     */
    public static ReturnHOResultSet4047RVO converyToReturnHOResultSet4047RVO(String xml, Class<ReturnHOResultSet4047RVO> c) {
        ReturnHOResultSet4047RVO returnHOResultSet4047RVO = null;
        try {
            JAXBContext context = JAXBContext.newInstance(c);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            returnHOResultSet4047RVO = (ReturnHOResultSet4047RVO) unmarshaller.unmarshal(new StringReader(xml));
        } catch (Exception e) {
            e.getMessage();
        }
        return returnHOResultSet4047RVO;
    }

    /**
     * xml转换成PingAnBankSelectBatchVO
     *
     * @param xml
     * @param c
     * @return
     */
    public static PingAnBankSelectBatchVO converyToPingAnBankSelectBatchVO(String xml, Class<PingAnBankSelectBatchVO> c) {
        PingAnBankSelectBatchVO pingAnBankSelectBatchVO = null;
        try {
            JAXBContext context = JAXBContext.newInstance(c);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            pingAnBankSelectBatchVO = (PingAnBankSelectBatchVO) unmarshaller.unmarshal(new StringReader(xml));
        } catch (Exception e) {
            e.getMessage();
        }
        return pingAnBankSelectBatchVO;
    }

    /**
     * xml转换成PingAnBankSelectAccountInfoVO
     *
     * @param xml
     * @param c
     * @return
     */
    public static PingAnBankSelectAccountInfoVO converyToPingAnBankSelectAccountInfoVO(String xml, Class<PingAnBankSelectAccountInfoVO> c) {
        PingAnBankSelectAccountInfoVO pingAnBankSelectAccountInfoVO = null;
        try {
            JAXBContext context = JAXBContext.newInstance(c);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            pingAnBankSelectAccountInfoVO = (PingAnBankSelectAccountInfoVO) unmarshaller.unmarshal(new StringReader(xml));
        } catch (Exception e) {
            e.getMessage();
        }
        return pingAnBankSelectAccountInfoVO;
    }


    /**
     * 20位的数字id
     */

    public static String getGuid() {
        long now = System.currentTimeMillis();
        //获取4位年份数字
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
        //获取时间戳
        String time = dateFormat.format(now);
        String info = now + "";
        //获取三位随机数
        int ran = (int) ((Math.random() * 9 + 1) * 100);
        return time + info + ran;
    }
}
